//======================================================
/**
 * @description begoina的入口文件,提供基本的方法
 * @author Brave Chan on 2019.5
 * @version 2.0.0
 */
//======================================================
import beStates from './vmp/beStates';
import { use, unload, destroyModule, setModulesDebug, getModuleByName, getModules } from './core/BEModules';
import BEApp from './core/BEApp';
import BEComponent from './core/BEComponent';
import BEPage from './core/BEPage';
import { isANothing, isFunction } from './utils/util';
import be_opt from './constant/be_opt';
import { APP_TYPE, PAGE_TYPE, COMPONENT_TYPE } from './constant/nodeType';
import AsyncList from './utils/be_asyncList';
//=======================================================
// let _debug = false;
const viewFactory = {
  [APP_TYPE]: BEApp,
  [PAGE_TYPE]: BEPage,
  [COMPONENT_TYPE]: BEComponent,
  defaultFn(origin) {
    throw new Error(`Expect a correct nodeType, maybe APP or PAGE or COMPONENT,but the param is not right`);
  }
};
const views = {
  [APP_TYPE]: App,
  [PAGE_TYPE]: Page,
  [COMPONENT_TYPE]: Component
}
//=======================================================
function BE(origin = {}, execList = []) {

  return function render(nodeType = 0) {
    const fn = viewFactory[nodeType] || viewFactory.defaultFn;
    const viewFn = views[nodeType] || viewFactory.defaultFn;
    if (isFunction(fn)) {
      return viewFn(fn(origin, execList));
    }
  }
}

BE.APP = APP_TYPE;
BE.PAGE_TYPE = PAGE_TYPE;
BE.COMPONENT = COMPONENT_TYPE;

export const APP = APP_TYPE;
export const PAGE = PAGE_TYPE;
export const COMPONENT = COMPONENT_TYPE;

//=======================================================
Object.defineProperties(BE, {
  debug: {
    set(value) {
      value = !!value;
      be_opt.debug = value
      setModulesDebug(value);
    },
    get() {
      return be_opt.debug;
    }
  }
});
/**
 * @public
 * @description 增加程序运行中需要使用的增强模块
 * @param {object} addModule [required] 增强模块
 * @param {object} config [optional] 模块设置
 * 如果设置了`config`参数并且模块也提供了`setup`方法，
 * 那么这个`config`对象将会作为`setup()`的参数传入模块中。
 * 模块利用其进行初始化配置。
 */
BE.use = use;
/**
 * @public
 * @description 卸载模块
 * @param {object} addModule [required] 增强模块
 */
BE.unload = unload;
/**
 * @public
 * @description 销毁模块
 * @param {object} addModule [required] 增强模块
 */
BE.destroyModule = destroyModule;

/**
 * @public
 * @description 组件代理对象工厂
 * @param {object} component [required] 原始组件对象
 * @returns {object} 合成后的适用于小程序Component()的对象
 */
BE.component = BEComponent;
/**
 * 页面代理对象工厂
 * @param {object} page [required] 声明式开发对象
 * @returns {object} 适用于小程序Page()的对象
 */
BE.page = BEPage;

/**
 * @public
 * @description 获取已装载模块映射
 * @returns { any }
 */
BE.getModules = getModules;

/**
 * @public
 * @description 使用模块名获取已装载的模块对象
 * @param {string} key [required] 模块名
 * @returns {any}
 */
BE.getModuleByName = getModuleByName;

Object.freeze(BE);

// 装载vmp模块
BE.use(beStates);
//=======================================================
export const BEAsyncList = AsyncList;
/**
 * @public
 * @description 根级代理工厂，也作为begonia的全局命名空间
 *
 * @param {object} app [required] 声明式开发对象
 * @returns {object} 适用于小程序App()的对象
 */
export default BE;
//=======================================================
